package com.jnu.myAccount.record;

import android.content.Context;

import com.jnu.myAccount.R;
import com.jnu.myAccount.activity.MainActivity;
import com.jnu.myAccount.menu.home.HomeViewModel;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class DataPackage implements Serializable {
    //文件名：账户#日期
    private final List<String> recordFileNameList = new ArrayList<>();

    private static DataPackage dataPackageInstance =null;
    private static List<Integer> StaticIconList =null;
    private static List<String> StaticKindList =null;

    private List<Integer> kindIconList;
    private List<String> kindTextList;
    private List<String> accountList;
    private Boolean needModify;
    private String modifyDate;
    private int modifyPosition;
    private Record recordNeedToModify;
    private HomeViewModel homeViewModel;

    //已创建日期列表
    private final List<String> dateList;
    //已创建的账单适配器列表
    private final List<FundAdapter> recordAdapterList;
    //账户信息字典
    private final Map<String,AccountFundInfo> accountFundInfoMap;

    public static List<Integer> getKindIconsInstance()
    {
        if(StaticIconList ==null)
        {
            StaticIconList = dataPackageInstance.kindIconList;
        }
        return StaticIconList;
    }

    public static List<String> getKindHeadsInstance()
    {
        if(StaticKindList ==null)
        {
            StaticKindList = dataPackageInstance.kindTextList;
        }
        return StaticKindList;
    }

    public static List<String> getStaticKindList() {
        return StaticKindList;
    }

    public List<String> getKindTextList() {
        return kindTextList;
    }

    public void setKindTextList(List<String> kindTextList) {
        this.kindTextList = kindTextList;
    }

    public List<Integer> getKindIconList() {
        return kindIconList;
    }

    public void setKindIconList(List<Integer> kindIconList) {
        this.kindIconList = kindIconList;
    }

    public List<String> getAccountList() {
        return accountList;
    }

    public void setAccountList(List<String> accountList) {
        this.accountList = accountList;
    }

    public List<String> getDateList() {
        return dateList;
    }

    public Map<String, AccountFundInfo> getAccountFundInfoMap() {
        return accountFundInfoMap;
    }

    public DataPackage() {
        //初始化图标、消费种类和账户列表
        initData();
        dateList = new ArrayList<>();
        recordAdapterList = new ArrayList<>();
        accountFundInfoMap = new HashMap<>();
        loadData();
    }

    public static DataPackage Instance() {
        if(dataPackageInstance ==null)
            dataPackageInstance = new DataPackage();
        return dataPackageInstance;
    }

    //初始化列表数据
    private void initData() {
        //初始化类型图标
        kindIconList = new ArrayList<>();
        kindIconList.add(R.drawable.ic_other);
        kindIconList.add(R.drawable.ic_food);
        kindIconList.add(R.drawable.ic_traffic);
        kindIconList.add(R.drawable.ic_wifi);
        kindIconList.add(R.drawable.ic_debt);
        kindIconList.add(R.drawable.ic_gift);
        kindIconList.add(R.drawable.ic_house);
        kindIconList.add(R.drawable.ic_hospital);
        kindIconList.add(R.drawable.ic_money_giving);
        kindIconList.add(R.drawable.ic_shop);
        kindIconList.add(R.drawable.ic_sport);
        kindIconList.add(R.drawable.ic_savings);
        kindIconList.add(R.drawable.ic_daily);
        kindIconList.add(R.drawable.ic_party);
        kindIconList.add(R.drawable.ic_stock);
        kindIconList.add(R.drawable.ic_travel);

        //初始化类型种类
        kindTextList = new ArrayList<>();
        kindTextList.add("其他");
        kindTextList.add("吃喝饮食");
        kindTextList.add("交通出行");
        kindTextList.add("通讯费用");
        kindTextList.add("欠债借款");
        kindTextList.add("人情礼物");
        kindTextList.add("房租水电");
        kindTextList.add("医疗费用");
        kindTextList.add("社交红包");
        kindTextList.add("逛街购物");
        kindTextList.add("运动健身");
        kindTextList.add("工资薪水");
        kindTextList.add("日常用品");
        kindTextList.add("聚餐聚会");
        kindTextList.add("基金理财");
        kindTextList.add("旅行旅游");

        //初始化账户列表
        accountList = new ArrayList<>();
        accountList.add("现金");
        accountList.add("微信");
        accountList.add("支付宝");
    }

    //删除单元记录
    public void removeRecord(Record record)
    {
        String account = record.getAccount();
        String date = record.getDateValue();
        //判断记录是否存在
        if(recordFileNameList.contains(account+"#"+date))
        {
            //获取记录的账户管理器
            FundAdapter recordAdapter = Objects.requireNonNull(accountFundInfoMap.get(account)).getFundInfoMap().get(date);

            //记录管理器删除记录后为空，则删除对应map和管理器
            assert recordAdapter != null;
            if(recordAdapter.removeFundFlowInfo(record))
            {
                //删除账户信息中对应的记录管理器、文件名和对应日期
                Objects.requireNonNull(accountFundInfoMap.get(account)).getFundInfoMap().remove(date);
                recordFileNameList.remove(account+"#"+date);
                recordAdapterList.remove(recordAdapter);
                dateList.remove(date);
                Collections.sort(dateList, String::compareTo);
            }
        }
    }

    public void addNewRecord(Record info)
    {
        if(info==null)
            return;
        String date = info.getDateValue();
        String account = info.getAccount();
        FundAdapter adapter;
        //若不存在该日期
        if(!dateList.contains(date)) {
            //创建新数据管理器
            adapter = new FundAdapter(account,date);
            //添加日期
            dateList.add(date);
            //整齐日期列表
            Collections.sort(dateList, String::compareTo);
        }
        else {
            //从记录管理器列表中读取对象
            adapter =  getAdapterByDateAndAccount(date,account);
            if(adapter==null)
            {
                //若管理器为空则新建
                adapter = new FundAdapter(account,date);
            }
        }
        //为账户信息添加记录管理器对象的引用
        Objects.requireNonNull(accountFundInfoMap.get(account)).addFundInfo(adapter);

        //为记录管理器添加新记录
        adapter.addNewFundFlowInfo(info);
        //若主码列表中不存在该主码
        if(!recordFileNameList.contains(account+"#"+date))
        {
            //添加新主码
            //添加引用到记录管理器列表中
            recordFileNameList.add(account+"#"+date);
            recordAdapterList.add(adapter);
        }
        //保存该记录管理器
        saveSingleData(adapter);
    }

    //根据日期和账户查找数据管理对象
    public FundAdapter getAdapterByDateAndAccount(String date, String account)
    {
        for(FundAdapter fundAdapter: recordAdapterList)
        {
            if(fundAdapter.getDate().equals(date)&&fundAdapter.getAccount().equals(account))
            {
                return fundAdapter;
            }
        }
        return null;
    }

    //保存单独管理器的数据
    public void saveSingleData(FundAdapter info)
    {
        if(info==null)
            return;
        try {
            ObjectOutputStream out = new ObjectOutputStream(
                    MainActivity.ContextInstance().openFileOutput(info.getFileName(),
                            Context.MODE_PRIVATE)
            );
            out.writeObject(info);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //从本地文件中加载数据
    public void loadData() {
        String[] strings;
        String regex = MainActivity.ContextInstance().getString(R.string.account_name_regex)
                +"#"+MainActivity.ContextInstance().getString(R.string.date_regex);
        //获取文件名
        for(String str : getFileNames())
        {
            //若为合法文件名
            if(str.matches(regex))
            {
                //读取数据管理类对象
                try{
                    ObjectInputStream in = new ObjectInputStream(
                            MainActivity.ContextInstance().openFileInput(str)
                    );
                    Object info = in.readObject();
                    if(info instanceof FundAdapter)
                    {
                        recordAdapterList.add((FundAdapter) info);
                    }
                    else {
                        MainActivity.ContextInstance().getFileStreamPath(str).getAbsoluteFile().delete();
                    }
                    in.close();
                    //添加对应主码
                    recordFileNameList.add(str);
                    strings = str.split("#");
                    //添加账户列表和日期列表
                    if(!accountList.contains(strings[0]))
                    {
                        accountList.add(strings[0]);
                    }
                    if(!dateList.contains(strings[1]))
                    {
                        dateList.add(strings[1]);
                    }
                } catch (IOException | ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
        //根据账户列表创建账户并读取余额
        for(String account: accountList)
        {
            accountFundInfoMap.put(account,new AccountFundInfo(account));
            Objects.requireNonNull(accountFundInfoMap.get(account)).loadData();
        }
        //为账户列表添加引用
        for(FundAdapter info : recordAdapterList)
        {
            Objects.requireNonNull(accountFundInfoMap.get(info.getAccount())).addFundInfo(info);
        }
        Collections.sort(dateList, String::compareTo);
    }

    //获取本地文件名列表
    public List<String> getFileNames() {
        ArrayList<String>  result = new ArrayList<>();
        File file = MainActivity.ContextInstance().getFileStreamPath("").getAbsoluteFile();
        File[] files = file.listFiles();
        for (int i = 0; i < Objects.requireNonNull(files).length; ++i) {
            if (!files[i].isDirectory()) {
                String fileName = files[i].getName();
                result.add(fileName);
            }
        }
        return result;
    }

    //获取所有单位记录
    private List<Record> getAllFundFlowInfo()
    {
        List<Record> list=new ArrayList<>();
        for(FundAdapter adapter: recordAdapterList)
        {
            if(adapter.getRecordList()!=null&&adapter.getRecordList().size()>0)
            {
                list.addAll(adapter.getRecordList());
            }
        }
        if(list.size()>0)
        {
            return list;
        }else {
            return null;
        }
    }

    //获取由日期为索引的单位记录列表字典
    public Map<String, List<Record>> getDateFundList()
    {
        Map<String, List<Record>> map = new HashMap<>();
        List<Record> list=getAllFundFlowInfo();
        if(list==null)
        {
            return null;
        }
        for(String d:dateList)
        {
            map.put(d,new ArrayList<>());
        }
        for(Record info:list) {
            Objects.requireNonNull(map.get(info.getDateValue())).add(info);
        }
        return map;
    }

    public float getBalance()
    {
        return Objects.requireNonNull(accountFundInfoMap.get("现金")).getBalance();
    }

    public void setBalance(float num)
    {
        Objects.requireNonNull(accountFundInfoMap.get("现金")).setBalance(num);
    }

    public void saveFundAdapter(FundAdapter info)
    {
        //检测info是否为null
        if(info == null)
            return;
        //写入本地文件
        try {
            ObjectOutputStream out = new ObjectOutputStream(
                    MainActivity.ContextInstance().openFileOutput(info.getFileName(),
                            Context.MODE_PRIVATE)
            );
            out.writeObject(info);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setRecordNeedToModify(Record recordNeedToModify) {
        this.recordNeedToModify = recordNeedToModify;
    }

    public Record getRecordNeedToModify() {
        return recordNeedToModify;
    }

    public HomeViewModel getHomeViewModel() {
        return homeViewModel;
    }

    public void setHomeViewModel(HomeViewModel homeViewModel) {
        this.homeViewModel = homeViewModel;
    }

    public Boolean getNeedModify() {
        return needModify;
    }

    public void setNeedModify(Boolean needModify) {
        this.needModify = needModify;
    }

    public String getModifyDate() {
        return modifyDate;
    }

    public void setModifyDate(String modifyDate) {
        this.modifyDate = modifyDate;
    }

    public int getModifyPosition() {
        return modifyPosition;
    }

    public void setModifyPosition(int modifyPosition) {
        this.modifyPosition = modifyPosition;
    }
}
